/* 
  Copyright (c) SilverLining 2015
  Date:    2016-1-7
  File:    heap.cpp  
  Description: 

*/

#include "stdafx.h"

namespace m
{
	namespace alloc
	{
		_aligned aligned;
		_pool pool;
	} // alloc
} // m

// Aligned new/delete
void* operator new (std::size_t count, m::alloc::_aligned&)
{
	void* ret = _aligned_malloc(count, ATOMIC_ALIGNMENT);
	if (!ret)
	{
		throw std::bad_alloc();
	}
	DBGALLOC(ret, count);
	return ret;
}

void* operator new[](std::size_t count, m::alloc::_aligned& aligned)
{
	return ::operator new(count, aligned);
}

void operator delete(void* data, m::alloc::_aligned&)
{
	DBGFREE(data);
	_aligned_free(data);
}

void operator delete[](void* data, m::alloc::_aligned& aligned)
{
	::operator delete(data, aligned);
}

// Pool new/delete
void* operator new (std::size_t count, m::alloc::_pool& pool)
{
	void* ret = pool.get(count);
	if (!ret)
	{
		throw std::bad_alloc();
	}
	// This is kind of a hack. We want to sneak the pool pointer into the object (the object won't initalize that area of memory on its own)
	// There's no guarantee as to what memory will be initalized to, but we know that if it's an object being allocated on the heap
	// It will be allocated using either this allocator or the aligned object allocator. If it's this allocator we put the pointer to the allocating pool
	// in the location the object expects it to be initialized in.
	if (count >= sizeof(m::object))
	{
		m::object* thisObject = (m::object*)ret;
		thisObject->_Pool = &pool;
	}
	DBGALLOC(ret, count);
	return ret;
}

void* operator new[](std::size_t count, m::alloc::_pool& pool)
{
	return ::operator new(count, pool);
}

void operator delete(void* data, m::alloc::_pool& pool)
{
	DBGFREE(data);
	pool.put(data);
}

void operator delete[](void* data, m::alloc::_pool& pool)
{
	::operator delete(data, pool);
}
